-- PRAGMA standard control signal mapping:
-- clk								=> clk
-- clk_48k							=> clk_48k
-- reset								=> reset
-- PAY ATTENTION:					RESET IS ACTIVE LOW
-- control_in	(0) 				=> enable
--					(2 downto 1) 	=> attenuation_factor
--					(6 downto 3) 	=> trigger_level
--					(7)			 	=> comp_exp
--
--	control_out	(0)				<= enable
--					(3 downto 1)	<= UNUSED
-- 
-- PCM_data_in_right				=> PCM_data_in_right
-- PCM_data_in_left				=> PCM_data_in_left
-- PCM_data_out_right			<= PCM_data_out_right
-- PCM_data_out_left				<= PCM_data_out_left

library ieee;
use ieee.std_logic_signed.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity PRM_time_1 is
  port(
    clk				: in std_logic;
	 clk_48k			: in std_logic;
    reset			: in std_logic;
	 
	 control_in		: in std_logic_vector(7 downto 0);
	 control_out	: out std_logic_vector(3 downto 0);
	 
    PCM_data_in_right	: in std_logic_vector(15 downto 0);
	 PCM_data_in_left		: in std_logic_vector(15 downto 0);
    PCM_data_out_right	: out std_logic_vector(15 downto 0);
	 PCM_data_out_left	: out std_logic_vector(15 downto 0)
    );
end entity PRM_time_1;

architecture behaviour of PRM_time_1 is
	signal enable 					: std_logic := '0';
	signal level_reached			: std_logic := '0';
	signal attenuation_factor	: std_logic_vector(2 downto 0) := (others => '0');
	signal trigger_level			: std_logic_vector(3 downto 0) := (others => '0');
	signal comp_exp				: std_logic := '0';
	
	signal threshold				: std_logic_vector(15 downto 0) := (others => '0');
	
	signal product					: std_logic_vector(16 downto 0) := (others => '0');
	
	signal attack_counter		: integer := 1023;
	signal release_counter		: integer := 1023;
begin
	
	enable 					<= control_in(0);
	attenuation_factor	<= '0' & control_in(2 downto 1);
	trigger_level			<= control_in(6 downto 3);
	comp_exp					<= control_in(7);
	
	control_out 			<= control_in(3 downto 0);
	
	threshold				<= '0' & trigger_level (3) & 
									'0' & trigger_level (2) &
									'0' & trigger_level (1) &
									'0' & trigger_level (0) &
									"00000000";
	
	PCM_data_out_left <= product(15 downto 0);		--use only the 16 relevant bits for output
	
	level_detect_p: process(clk_48k, reset)
	begin
		if reset = '0' then
			attack_counter		<= 1023;
			release_counter	<= 1023;
			level_reached 		<= '0';
		elsif clk_48k'event and clk_48k = '0' then
			if comp_exp = '1' then		--compression
				if PCM_data_in_left > threshold and attack_counter = 0 then
					release_counter 	<= 1023;
				elsif PCM_data_in_left > threshold then
					attack_counter		<= attack_counter - 1;
					release_counter 	<= 1023;
				elsif release_counter = 0 then
					attack_counter 	<= 1023;
					level_reached 		<= '0';
				elsif attack_counter = 0 then
					level_reached		<= '1';
					release_counter 	<= release_counter - 1;
				else
					attack_counter		<= attack_counter - 1;
					release_counter	<= release_counter - 1;
				end if;
			else								--expansion
				if PCM_data_in_left > threshold and release_counter = 0 then
					attack_counter <= 1023;
				elsif PCM_data_in_left > threshold then
					release_counter	<= release_counter - 1;
					attack_counter		<= 1023;
				elsif attack_counter = 0 then
					release_counter 	<= 1023;
					level_reached 		<= '1';
				elsif release_counter = 0 then
					level_reached		<= '0';
					attack_counter		<= attack_counter - 1;
				else
					attack_counter		<= attack_counter - 1;
					release_counter	<= release_counter - 1;
				end if;
			end if;
		end if;
	end process;
	
	function_p: process(clk_48k, reset)
	begin
		if reset = '0' then
			product <= (others => '0');
			PCM_data_out_right <= (others => '0');
		elsif clk_48k'event and clk_48k = '0' then
			PCM_data_out_right <= (others => '0');
			if enable = '1' then
				if level_reached = '1' then
					product <= PCM_data_in_left(15 downto 2) * attenuation_factor;
				else
					product <= '0' & PCM_data_in_left;
				end if;
			else
				product <= '0' & PCM_data_in_left;
				PCM_data_out_right <= PCM_data_in_right;
			end if;
		end if;
	end process;
end architecture behaviour;
